#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "wiringSerial.h"

int mySerialOpen (const char *device, const int baud){
	struct termios options ;
	speed_t myBaud ;
	int     status, fd ;

	switch (baud)
	{
		case    9600:	myBaud =    B9600 ; break ;
		case  115200:	myBaud =  B115200 ; break ;
		default:
						return -2 ;
	}

	if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
		return -1 ;

	//fcntl 的所有功能都围绕着一个核心思想：修改一个打开文件的属性和行为
	fcntl (fd, F_SETFL, O_RDWR) ;

	// Get and modify current options:
	//读取一个终端设备（如串口、控制台）,fd 现在所指的是串口设备，当前的配置参数，并将这些参数填充到一个 struct termios 结构体中。
	tcgetattr (fd, &options) ;
	// 修改options,设置原始模式，去掉与用户交互的终端配置，只用于原始数据通信的配置
	cfmakeraw   (&options) ;
	cfsetispeed (&options, myBaud) ;
	cfsetospeed (&options, myBaud) ;

	options.c_cflag |= (CLOCAL | CREAD) ;
	options.c_cflag &= ~PARENB ;
	options.c_cflag &= ~CSTOPB ;
	options.c_cflag &= ~CSIZE ;
	options.c_cflag |= CS8 ;
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
	options.c_oflag &= ~OPOST ;

	options.c_cc [VMIN]  =   0 ;
	options.c_cc [VTIME] = 100 ;	// Ten seconds (100 deciseconds)

	//应用已经修改好的配置
	tcsetattr (fd, TCSANOW, &options) ;
	//获取fd所指向的串口设备的属性
	ioctl (fd, TIOCMGET, &status);
	//修改属性
	status |= TIOCM_DTR ;
	status |= TIOCM_RTS ;
	//应用属性
	ioctl (fd, TIOCMSET, &status);

	usleep (10000) ;	// 10mS

	return fd ;
}

void mySerialWriteString (const int fd, const char *buffer)
{ 
	int ret;
	ret = write (fd, buffer, strlen (buffer));
	if (ret < 0)
		printf("Serial Puts Error\n");
}

int mySerialReadString (const int fd, char * buffer)
{
	int n_read = 0;
	if((n_read = read(fd, buffer, 32)) < 0){
		return -1;
	}

	return n_read;
}

int mySerialGetChar(const int fd){
	int x;
	if(read(fd, &x, 1) != 1){
		return -1;
	}
	return x;
}

